home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 11 - 1995 / 11.02 Feb 95 / Yenta / C Libraries / InstallDefProc.c < prev    next >
Encoding:
Text File  |  1996-04-04  |  4.7 KB  |  163 lines  |  [TEXT/KAHL]

  1. /*
  2.  * EmbeddedDefProc *
  3.  * This unit contains "InstallDefProc", a procedure that allows a program to
  4.  * use definition routines imbedded in the program's source, as opposed to
  5.  * requiring a separate resource. This mechanism is useful for debugging most
  6.  * defprocs, and for "hiding" them from the user.
  7.  */
  8.  
  9. /* USING THE EMBEDDED DEF PROC:
  10.  *
  11.  *    To use the embedded def proc, you need to do the following steps:
  12.  *
  13.  *    1) Create a new project that you are going to use to test the CDEF, MDEF, LDEF
  14.  *    etc. you are debugging
  15.  *
  16.  *    2) Create a resource file for this project.  Now create a resource of the type that
  17.  *    you are trying to debug and give it id 128.
  18.  *
  19.  *    3) Using the resedit hex editor, fill this resource with a jump instruction,
  20.  *     followed by 8 0's. (See comments on for InstallDefProc() below.) Save
  21.  *    the file.
  22.  *
  23.  *    4) In the project file, add the source file that contains your code for your
  24.  *    resource, the code to check test your resource, and of course the install
  25.  *    def proc procedure.  A good thing to note here is that to make sure you
  26.  *    rename the main of your resource to something like myresource_main
  27.  *    etc.
  28.  *
  29.  *    5)  Now add the following as the first line in your main.
  30.  *     InstallDefProc(CurResFile(),
  31.  *        Myrtype',128,(Ptr)&myresource_main);
  32.  *    where 'Myrtype' is actually the type of your resource, i.e. 'LDEF', 'CDEF'
  33.  *     etc. and myresource_main is the main function of your code resource.
  34.  *
  35.  *
  36.  *    Now when you run your test, you should be able to single step through the code
  37.  *    using Think C's source level debugger.
  38.  */
  39.  
  40.  // Assumes inclusion of <MacHeaders>
  41. #include <Traps.h>
  42. #include <InstallDefProc.h>
  43.  
  44. Boolean TrapAvailable( short theTrap);
  45. void FlushCache(void);
  46.  
  47. typedef struct {
  48.     short     jmpInstr;
  49.     Ptr     jmpAddr;
  50. } JmpRecord, *JmpPtr, **JmpHandle;
  51.  
  52. /*
  53.  * TrapAvailable
  54.  * Check whether a certain trap exists on this machine.
  55.  */
  56.  
  57. Boolean TrapAvailable( short theTrap)
  58. {
  59.     TrapType     tType;
  60.     short    numToolBoxTraps;
  61.  
  62.     // first determine the trap type
  63.  
  64.     tType = (theTrap & 0x800) > 0 ? ToolTrap : OSTrap;
  65.  
  66.     // next find out how many traps there are
  67.  
  68.     if (NGetTrapAddress( _InitGraf, ToolTrap) == NGetTrapAddress( 0xAA6E,
  69.              ToolTrap))
  70.             numToolBoxTraps = 0x200;
  71.     else
  72.             numToolBoxTraps = 0x400;
  73.  
  74.     // check if the trap number is too big for the
  75.     // current trap table
  76.  
  77.     if (tType == ToolTrap)
  78.     {
  79.             theTrap &= 0x7FF;
  80.             if (theTrap >= numToolBoxTraps)
  81.                     theTrap = _Unimplemented;
  82.     }
  83.  
  84.     // the trap is implemented if its address is
  85.     // different from the unimplemented trap
  86.  
  87.     return (NGetTrapAddress( theTrap, tType) !=
  88.                     NGetTrapAddress(_Unimplemented, ToolTrap));
  89. }
  90.  
  91. /*
  92.  * FlushCache
  93.  * Flush the CPU cache(s). This is required on the 68040 after modifying
  94.  *    code.
  95.  */
  96.  
  97. #define _CacheFlushTrap    0xA0BD
  98.  
  99. void FlushCache(void)
  100. {
  101.     if (TrapAvailable( _CacheFlushTrap))
  102.             asm
  103.             {
  104.                     dc.w _CacheFlushTrap
  105.             }
  106. }
  107.  
  108. /*
  109.  * InstallDefProc works by looking for a resource of the desired resource
  110.  * type and ID in the resource file specified by "dpPath"; if you're installing
  111.  * definition routines at program startup, you can pass CurResFile() as the
  112.  * first argument.  The defproc resource is then patched to point to the
  113.  * procedure address given in "dpAddr".
  114.  *
  115.  * If the resource is not found in the resource file, a debugger trap is
  116.  * executed.  To avoid this, you should create a 6-byte resource (it can be all
  117.  * zeros) of the defproc's type and ID, and place it in your program's
  118.  * resource file.
  119.  *
  120.  * Caveats:
  121.  *
  122.  * You probably don't want to install stub defprocs in the system resource file.
  123.  * Also remember that there are reserved resource ID's from 0 to 127; you should
  124.  * use resource ID's 128 or higher for your defprocs.
  125.  *
  126.  * Procedures that are installed should be in the main segment, and
  127.  * InstallDefProc only need be called once.
  128.  *
  129.  * HOW IT WORKS:
  130.  *
  131.  * In the normal case, the system loads a procedure resource (an LDEF, for
  132.  * example), and jumps to its beginning.  InstallDefProc provides this
  133.  * functionality for procedures in your program by providing a 6-byte stub
  134.  * resource, which contains $4EF9, followed by a long word.  The $4EF9 is a
  135.  * 68000 long jump instruction, and the long word is the address to which to
  136.  * jump.  So the system calls this dummy defproc, which in turn jumps to the
  137.  * address passed.
  138.  */
  139.  
  140. void InstallDefProc(short dpPath, ResType dpType, short dpID, Ptr dpAddr)
  141. {
  142.     JmpHandle     jH;
  143.     short     savePath;
  144.  
  145.     savePath = CurResFile();
  146.     UseResFile(dpPath);
  147.  
  148.     jH = (JmpHandle)GetResource(dpType, dpID);
  149.     UseResFile(savePath);
  150.  
  151.     if (!jH)            /* is there no defproc resource? */
  152.             DebugStr("\pStub Defproc Not Found!");
  153.  
  154.     (**jH).jmpAddr = dpAddr;
  155.     (**jH).jmpInstr = 0x4EF9;
  156.     FlushCache();
  157.  
  158.     HUnlock((Handle)jH);
  159.     MoveHHi((Handle)jH);
  160.     HNoPurge((Handle)jH);    /* make this resource nonpurgeable */
  161. }
  162.  
  163.